

Creating a plan starts with identifying and referencing the application code that you want to package and automate. Habitat provides several different ways to refer and include application code in your package: by downloading a tarball of the source and compiling it when building the package, by referring to a local source directory, or by using a pre-built binary and bundling it up in your package.

To demonstrate Habitat code residing in the same repo as your source code, you are going to clone a simple Node.js application with a `habitat` subdirectory already created for you. Then you will modify the plan and do a test build to verify you have the basic process working correctly. By having the Habitat plan live in the same directory as your source code, the Habitat package for your application can be built right alongside your source code for testing and deployment purposes.

## Clone the project
The Node.js application in this tutorial is a simple web app that displays a message to anyone who connects to the application. You can configure both the listening port and the message.

<% if is_windows %>
1. Change the default Git for Windows CRLF line endings setting to be LF line endings.

       git config --global core.eol lf
       git config --global core.autocrlf input
<% end %>

1. Clone the habitat-example-plans repo onto your local machine. In this example, a directory called `habitat-example-plans` will be created in the `$HOME` directory.

       cd ~
       git clone https://github.com/habitat-sh/habitat-example-plans

1. After you have successfully cloned the repo, change directory to the `mytutorialapp` directory.

       cd ~/habitat-example-plans/mytutorialapp

The `/source` directory contains three files that comprise the Node.js application: `server.js`, `package.json`, and `config.json`.

The `server.js` file is the main file in our web app. It uses the [nconf module](https://github.com/indexzero/nconf) to retrieve the `message` and `port` configuration values that are set in the `config/config.json` file.

The `config.json` file is the default configuration file that you would use if this was an existing application running on a VM or in a container. When you create and configure your package, you will create a templatized version of this file that will be used when the service starts up.

And finally, because we are using npm to start up our Node.js web app, the npm binary looks for a `package.json` file to describe the Node.js app project and its dependencies.

The `/habitat` directory contains the heart of a Habitat package: the plan. This is a directory comprised of shell scripts and optional configuration files that define how you download, configure, make, install, and manage the lifecycle of the software in the package. Currently, the plan in `/habitat-example-plans/habitat` only contains `plan.sh`, which you will populate and add to in the following sections.

> Note: The habitat-example-plans repo also contains a `mytutorialapp_finished` directory that you can reference at any time. It also contains an alternative `plan.sh` file that downloads the Node.js application source from a tarball instead of a local directory to show you how you would need to alter your `plan.sh` file in that scenario.

## Start with the basics
Now that you have cloned the `habitat-example-plans` repo and understood its structure, it is time to define the plan. At a bare minimum, a plan must have a `plan.sh` at the root of the directory. This file specifies where the source code or binary is, how it should be built by the `hab-pkg-build` command, and how the supervisor should start it at runtime.

In your terminal window, do the following:

1. Change directories to your plan directory (also known as the plan context).

       cd ~/habitat-example-plans/mytutorialapp/habitat

2. Open `plan.sh` in your text editor.

       $EDITOR plan.sh

   Your `plan.sh` should look like this:

       pkg_origin=
       pkg_name=mytutorialapp
       pkg_version=0.2.0
       pkg_maintainer="The Habitat Maintainers <humans@habitat.sh>"
       pkg_license=()
       pkg_upstream_url=https://github.com/habitat-sh/habitat-example-plans
       pkg_source=nosuchfile.tar.gz
       pkg_deps=()
       pkg_expose=()

Let's walk through these settings:

- The `pkg_origin`, `pkg_name`, and `pkg_version` settings form the package identifier information.
- The `pkg_maintainer` and `pkg_license` settings provide contact and license type information.
- The `pkg_upstream_url` is used to provide project website metadata.
- The `pkg_source` is a URL that specifies where to download the source from. If you are building the source locally, or do not need to download a file, you must still provide a non-empty string value.
- The `pkg_deps` corresponds to the runtime package dependencies, and `pkg_expose` opens a network port when a Docker container is created (must be used along with the `-p` runtime option to publish it to the host machine).

## Modify the plan

We now have a skeleton plan, but we need to modify some of its settings before we can continue.

1. Set the `pkg_origin` value to the one created for you by `hab setup`. For the examples in this tutorial, it will be set to "myorigin". The "core" origin name is reserved. That name is used by the Habitat maintainers group to create foundational packages that you can use as dependencies in your packages. If you would like to browse them, they are located in the Habitat [core plans repo](https://github.com/habitat-sh/core-plans).
2. The `pkg_name` value has been set to "mytutorialapp". This matches the name of the npm package name in `/source/package.json` and should be left as is. The same goes for `pkg_version`.

    > Note: A previous version of the tutorial used version `0.1.0`; however, the content related to that version no longer works with the latest version of Habitat.
3. Because this is a tutorial, you don't have to change the `pkg_maintainer` value to your email address; however, when you upload packages for others to consume, you should include your contact information.
4. Leave the `pkg_upstream_url` and `pkg_source` values as they are. The `pkg_upstream_url` is a metadata setting for your project/application -- in this case, the `habitat-example-plans` GitHub repo. The `pkg_source` setting is required, but since you will be building your package with cloned source files, you do not need to specify a valid URL. 
5. Our Node.js application depends on the `node` and `npm` binaries at runtime, so include one of the core Habitat packages, `core/node`, as a runtime dependency. Transitive dependencies, such as `core/glibc` used by `core/node`, do not need to be listed when creating plans.

        pkg_deps=(core/node)

   > Note: Later on in this topic we are going to install the `nconf` module into our package, which requires the `npm` binary; however, we do not need to include `core/node` as a build dependency because the build script automatically installs build and runtime dependencies and adds their bin directories to the `$PATH` variable before building the package. So, if you need the same dependent binary for both build and runtime operations, you only need to include it as a runtime dependency.

6. Set the `pkg_expose` value to `8080`. The `pkg_expose` setting creates an `EXPOSE` instruction in a generated Dockerfile, which we will use to create an optional Docker container; however, specifying the `pkg_expose` value does not publish this port for access by the host machine. We will do that later.

   Add the following line to your plan:

        pkg_expose=(8080)

It's important to note that the Node.js application in this tutorial does not create any new binaries or libraries of its own; however, for those packages that compile binaries and/or libraries, you must also include settings that specify the directory names where those files will be located, such as:

     pkg_bin_dirs=(bin)
     pkg_include_dirs=(include)
     pkg_lib_dirs=(lib)

## Add in callbacks

Callbacks in a plan are simply overrides to existing functions that are called by the `hab-plan-build` script at build time. Unless your plan is for a simple software library that only requires the default behavior (compiling and installing a downloaded tarball), you will probably have to use one or more callbacks.

Our source files need to move from the `/source` directory in our repo to our package at buildtime. This requires us to first override the **do_download()**, **do_verify()**, and **do_unpack()** callbacks. The default implementation for these callbacks is to download a tarball of your source code, verify its checksum, and then extract the contents of the tarball into a temporary directory defined by the `$HAB_CACHE_SRC_PATH` variable, and since the source code for this tutorial is in the same repo, we simply will return the success exit code `0` for each callback.

Add the following to your `plan.sh` file.

~~~ bash
do_download() {
  return 0
}

do_verify() {
  return 0
}

do_unpack() {
  return 0
}
~~~

The second set of callbacks that we will implement is for **do_build()** and **do_install()**. By default, these functions perform simple tasks like calling `make` and `make install`. We will use them to copy source files into the correct temp and package directories as well as install our `nconf` npm module.

Add the following to your `plan.sh` file under the previous callbacks. Comments in each callback provide additional detail.

~~~ bash
do_build() {
  # The mytutorialapp source code is in a relative directory, so you must copy the
  # contents of the source directory into your $HAB_CACHE_SRC_PATH/$pkg_dirname as this
  # is the same path that Habitat would use if you downloaded a tarball of the source code.
  cp -vr $PLAN_CONTEXT/../source/* $HAB_CACHE_SRC_PATH/$pkg_dirname

  # This installs both npm as well as the nconf module we listed as a
  # dependency in package.json.
  npm install
}

do_install() {
  # Our source files were copied over to HAB_CACHE_SRC_PATH/$pkg_dirname in do_build(),
  # and now they need to be copied from that directory into the root directory of our package
  # through the use of the pkg_prefix variable.
  cp package.json ${pkg_prefix}
  cp server.js ${pkg_prefix}

  # Copy over the nconf module to the package that we installed in do_build().
  mkdir -p ${pkg_prefix}/node_modules/
  cp -vr node_modules/* ${pkg_prefix}/node_modules/
}
~~~

Here's what your `plan.sh` should look like in the end:

~~~ bash
pkg_origin=<youroriginname>
pkg_name=mytutorialapp
pkg_version=0.2.0
pkg_maintainer="The Habitat Maintainers <humans@habitat.sh>"
pkg_license=()
pkg_upstream_url=https://github.com/habitat-sh/habitat-example-plans
pkg_source=nosuchfile.tar.gz
pkg_deps=(core/node)
pkg_expose=(8080)

do_download() {
  return 0
}

do_verify() {
  return 0
}

do_unpack() {
  return 0
}

do_build() {
  # The mytutorialapp source code is in a relative directory, so you must copy the
  # contents of the source directory into your $HAB_CACHE_SRC_PATH/$pkg_dirname as this
  # is the same path that Habitat would use if you downloaded a tarball of the source code.
  cp -vr $PLAN_CONTEXT/../source/* $HAB_CACHE_SRC_PATH/$pkg_dirname

  # This installs both npm as well as the nconf module we listed as a
  # dependency in package.json.
  npm install
}

do_install() {
  # Our source files were copied over to HAB_CACHE_SRC_PATH/$pkg_dirname in do_build(),
  # and now they need to be copied from that directory into the root directory of our package
  # through the use of the pkg_prefix variable.
  cp package.json ${pkg_prefix}
  cp server.js ${pkg_prefix}

  # Copy over the nconf module to the package that we installed in do_build().
  mkdir -p ${pkg_prefix}/node_modules/
  cp -vr node_modules/* ${pkg_prefix}/node_modules/
}
~~~

For a complete listing of all of the plan settings, callbacks, and runtime hooks, see the [Plan syntax guide](/docs/reference/plan-syntax).